﻿using UnityEditor;
using UnityEngine;
using System;
using System.IO;
using Newtonsoft.Json;
using System.Collections.Generic;

namespace SkillEditor
{
    public class SkillEditorWindow : EditorWindow
    {
        [MenuItem("Window/SkillEditor")]
        public static void Open()
        {
            var window = GetWindow<SkillEditorWindow>();
            window.titleContent = new GUIContent("技能编辑器");
            window.Init();
            window.Show();
        }

        private string[] SkillTypeLabes = new string[] { "普攻", "主动技能", "触发技能", "光环", "Buff", "护盾", "被动技能" };
        private string[] TargetTypeLabes = new string[] { "当前目标", "敌人", "队友", "自己", "己方", "空目标", "所有人" };
        private string[] TargetPickTypeLabes = new string[] { "正常", "随机不重复", "随机重复" };
        private string[] RangeTypeLabes = new string[] { "圆形", "直线", "扇形" };
        private string[] TimeTypeLabes = new string[] { "正常", "攻速修正" };
        private string[] ShieldTypeLabes = new string[] { "护盾", "物理伤害护盾", "法术伤害护盾", "抵挡伤害护盾" };
        private string[] SuperposeTypeLabes = new string[] { "唯一","替换","叠加","独立" };

        public string[] triggerLabels;
        public int[] triggers;

        public string filePath;


        public SkillEditorConfig config;

        private List<string> arrSkillFiles;
        private SkillEditorSpaceWindow spaceEditor;
        private CastSkillEditorData sourceData;
        private CastSkillEditorData data;
        private string dataAsset;


        public void Init()
        {
            var dicTriggers = SkillEditorSpaceWindow.dicTriggers;
            triggers = new int[dicTriggers.Count + 1];
            triggerLabels = new string[dicTriggers.Count + 1];
            triggers[0] = 0;
            triggerLabels[0] = " - ";
            int index = 1;
            foreach (var item in dicTriggers)
            {
                triggers[index] = item.Key;
                triggerLabels[index] = item.Key + "." + item.Value;
                index++;
            }

            filePath = config.skillFolder;
            arrSkillFiles = new List<string>(Directory.GetFiles(filePath, "*.json"));

            InitStyle();
        }

        private void OnGUI()
        {
            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal(EditorStyles.toolbar);

            if (GUILayout.Button("打开文件", EditorStyles.toolbarButton))
            {
                var newFilePath = EditorUtility.OpenFolderPanel("Open...", "", "json");
                if (string.IsNullOrEmpty(newFilePath))
                    return;
                filePath = newFilePath;
                arrSkillFiles = new List<string>(Directory.GetFiles(filePath, "*.json"));
            }

            if (GUILayout.Button("新建", EditorStyles.toolbarButton))
            {
                string newFile = EditorUtility.SaveFilePanel("新建", filePath, "", "json");
                if (string.IsNullOrEmpty(newFile))
                {
                    return;
                }
                newFile = newFile.Trim();
                CastSkillEditorData data = new CastSkillEditorData();
                data.id = Path.GetFileNameWithoutExtension(newFile);
                JsonSerializerSettings settings = new JsonSerializerSettings() {
                    Formatting = Formatting.Indented,
                    NullValueHandling = NullValueHandling.Ignore,
                    DefaultValueHandling = DefaultValueHandling.Ignore
                };
                File.WriteAllText(newFile, JsonConvert.SerializeObject(data, settings));

                if (arrSkillFiles.IndexOf(newFile) == -1)
                    arrSkillFiles.Add(newFile);
                arrSkillFiles.Sort();
                SetData(newFile, data);
            }

            if (GUILayout.Button("刷新", EditorStyles.toolbarButton))
            {
                arrSkillFiles = new List<string>(Directory.GetFiles(filePath, "*.json"));
            }

            if (GUILayout.Button("保存", EditorStyles.toolbarButton))
            {
                SaveChanges();
            }

            if (GUILayout.Button("删除", EditorStyles.toolbarButton))
            {
                if (string.IsNullOrEmpty(dataAsset) == false)
                    AssetDatabase.DeleteAsset(dataAsset);

                arrSkillFiles = new List<string>(Directory.GetFiles(filePath, "*.json"));
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space();

            if (arrSkillFiles != null)
            {
                ShowFiles();
                EditorGUILayout.Space(50f);
            }

            if (data != null)
            {
                ShowCastSkill();
            }

            if (data != null)
            {
                EditorGUILayout.Space(50f);

                EditorGUILayout.BeginVertical();
                GUILayout.Label("SkillContent", EditorStyles.boldLabel);
                EditorGUILayout.Space();

                if (data.skillContent != null)
                {
                    for (int i = 0; i < data.skillContent.spaces.Length; i++)
                    {
                        GUILayout.Label(data.skillContent.spaces[i].id);
                    }
                }
                else
                {
                    GUILayout.Label("-");
                }

                if (GUILayout.Button("编辑"))
                {
                    spaceEditor = GetWindow<SkillEditorSpaceWindow>("SkillEditor");
                    spaceEditor.Init();

                    if (data.skillContent == null)
                    {
                        data.skillContent = new SkillContentData();
                    }

                    spaceEditor.SetData(ref data.skillContent);
                }

                if (GUILayout.Button("删除"))
                {
                    data.skillContent = null;
                }

                EditorGUILayout.EndVertical();
            }

            GUILayout.FlexibleSpace();

            EditorGUILayout.EndHorizontal();

            GUILayout.EndVertical();
        }

        public override void SaveChanges()
        {
            base.SaveChanges();

            JsonSerializerSettings settings = new JsonSerializerSettings()
            {
                Formatting = Formatting.Indented,
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore,
            };
            string fileContent = JsonConvert.SerializeObject(data, settings);
            File.WriteAllText(dataAsset, fileContent);
            this.sourceData = JsonConvert.DeserializeObject<CastSkillEditorData>(fileContent);
        }

        private Vector2 vt2Files;
        private Vector2 vt2BuffAttr;

        private void ShowFiles()
        {
            GUILayout.BeginVertical(GUILayout.Width(308f));

            GUILayout.Label("SkillList", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            vt2Files = GUILayout.BeginScrollView(vt2Files);

            for (int i = 0; i < arrSkillFiles.Count; i++)
            {
                string fileName = Path.GetFileNameWithoutExtension(arrSkillFiles[i]);

                if (GUILayout.Button(fileName, EditorStyles.miniButtonMid))
                {
                    string txtContent = File.ReadAllText(arrSkillFiles[i]);
                    CastSkillEditorData data = JsonConvert.DeserializeObject<CastSkillEditorData>(txtContent);

                    if (data.id != fileName)
                    {
                        //hasUnsavedChanges = true;
                        data.id = fileName;
                    }
                    SetData(arrSkillFiles[i], data);
                }
            }

            GUILayout.EndScrollView();

            GUILayout.EndVertical();
        }



        private void ShowCastSkill()
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(308f));
            GUILayout.Label("SkillParameter", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            //GUILayout.Label("-----------------------------------------------------------");

            EditorGUILayout.TextField("技能ID:", data.id);
            data.type = Popup("技能类型:", data.type, SkillTypeLabes, sourceData.type);
            data.asset = TextField("显示资源:", data.asset,sourceData.asset);

            //GUILayout.Label("-----------------------------------------------------------");

            if (data.type == 0)
            {
                EditorGUILayout.HelpBox("普攻是特殊的主动技能", MessageType.Info);
            }
            else if (data.type == 1)
            {
                EditorGUILayout.HelpBox("主动技能是有施法、引导、结束时间的触发技能", MessageType.Info);
            }
            else if (data.type == 2)
            {
                EditorGUILayout.HelpBox("触发技能是根据触发时机生效的技能", MessageType.Info);
            }
            else if (data.type == 6)
            {
                EditorGUILayout.HelpBox("被动技能是不受角色状态限制，可以时间触发的触发技能", MessageType.Info);
            }

            EditorGUILayout.Space();

            if (data.type == 0 || data.type == 1)
            {
                GUILayout.Label("-----------------------------------------------------------");
                data.weight = IntField("优先级:", data.weight,sourceData.weight);
                data.cost = IntField("技能消耗:", data.cost, sourceData.cost);
                data.cold = IntField("技能冷却:", data.cold, sourceData.cold);

                GUILayout.Label("-----------------------------------------------------------");

                if (data.timeType == 1)
                {
                    EditorGUILayout.HelpBox("攻速修正会根据攻速比例修改释放时间", MessageType.None);
                }
                data.timeType = Popup("时间类型:", data.timeType, TimeTypeLabes, sourceData.timeType);

                if (data.timeType == 1)
                {
                    EditorGUILayout.HelpBox("根据攻速提高释放速度\n？？？？？？？？", MessageType.None);
                    data.timeBouns = FloatField("标准攻速:", data.timeBouns,sourceData.timeBouns);
                }

                data.castTime = IntField("前摇时间(ms):", data.castTime, sourceData.castTime);
                data.channelTime = IntField("引导时间(ms):", data.channelTime, sourceData.channelTime);

                if (data.channelTime > 0)
                {
                    if (data.intervalTime == null)
                        data.intervalTime = new int[1] { 0 };

                    data.channelLoop = Toggle("循环触发", data.channelLoop == 1,sourceData.channelLoop == 1) ? 1 : 0;

                    EditorGUILayout.HelpBox("引导过程中触发点，填写间隔时长", MessageType.None);
                    int count = data.intervalTime.Length;
                    count = IntField("触发数", count, sourceData.intervalTime != null ? sourceData.intervalTime.Length : 0);

                    if (count != data.intervalTime.Length)
                    {
                        List<int> listTemp = new List<int>(data.intervalTime);
                        if (count < data.intervalTime.Length)
                        {
                            listTemp.RemoveRange(count, data.intervalTime.Length - count);
                        }
                        else
                        {
                            for (int i = listTemp.Count; i < count; i++)
                            {
                                listTemp.Add(0);
                            }
                        }
                        data.intervalTime = listTemp.ToArray();
                    }

                    for (int i = 0; i < data.intervalTime.Length; i++)
                    {
                        data.intervalTime[i] = EditorGUILayout.IntField(" 间隔" + i + ":", data.intervalTime[i]);
                    }
                }
                else
                {
                    data.intervalTime = null;
                }

                data.endTime = IntField("后摇时间(ms):", data.endTime, sourceData.endTime);
            }
            else if (data.type == 6)
            {
                GUILayout.Label("-----------------------------------------------------------");
                data.cost = IntField("技能消耗:", data.cost, sourceData.cost);
                data.cold = IntField("技能冷却(ms):", data.cold, sourceData.cold);
            }

            if (data.type == 0 || data.type == 1 || data.type == 6)
            {
                GUILayout.Label("-----------------------------------------------------------");

                data.targetType = Popup("目标类型:", data.targetType, TargetTypeLabes, sourceData.targetType);
                EditorGUILayout.HelpBox("目标数量为0时表示不限数量", MessageType.None);
                data.targetNum = IntField("目标数量:", data.targetNum, sourceData.targetNum);

                data.targetPickType = Popup("选区方式:", data.targetPickType, TargetPickTypeLabes, sourceData.targetPickType);

                EditorGUILayout.HelpBox("每个阶段都重新寻找目标", MessageType.None);
                data.targetUpdate = Toggle("更新目标:", data.targetUpdate == 1, sourceData.targetUpdate == 1) ? 1 : 0;

                EditorGUILayout.HelpBox("范围为0时表示攻击射程", MessageType.None);
                data.rangeType = Popup("范围类型:", data.rangeType, RangeTypeLabes, sourceData.rangeType);
                data.range = IntField("范围距离:", data.range, sourceData.range);
            }

            if (data.type == 4)
            {
                GUILayout.Label("-----------------------------------------------------------");
                                
                data.duration = IntField("持续时长", data.duration, sourceData.duration);
                data.enabledClear = Toggle("是否可清除:", data.enabledClear == 1, sourceData.enabledClear == 1) ? 1 : 0;
                data.stackType = Popup("叠加方式", data.stackType, SuperposeTypeLabes, sourceData.stackType);
                if(data.stackType == 2 || data.stackType == 3)
                    data.stack = IntField("最大层数", data.stack, sourceData.stack);

                int triggerIndex = 0;
                if (data.trigger > 0)
                    triggerIndex = Array.IndexOf<int>(triggers, data.trigger);
                if (triggerIndex == -1)
                    triggerIndex = 0;
                triggerIndex = Popup("触发时机:", triggerIndex, triggerLabels, Array.IndexOf<int>(triggers, sourceData.trigger));
                data.trigger = triggers[triggerIndex];

                if (data.trigger > 0)
                {
                    data.interval = IntField("触发间隔", data.interval, sourceData.interval);
                    data.count = IntField("触发次数", data.count, sourceData.count);
                }
            }

            if (data.type == 5)
            {
                GUILayout.Label("-----------------------------------------------------------");

                data.shieldType = Popup("护盾类型", data.shieldType, ShieldTypeLabes, sourceData.shieldType);
                EditorGUILayout.HelpBox("SheildCreate里创建值和改值相加为最终值", MessageType.None);
                if (data.shieldType == 3)
                {
                    EditorGUILayout.HelpBox(ShieldTypeLabes[3] + " 的护盾值为格挡次数", MessageType.None);
                }
                data.shield = IntField("护盾值", data.shield, sourceData.shield);
                EditorGUILayout.HelpBox("持续时长为0时，护盾消耗完消失", MessageType.None);
                data.duration = IntField("持续时长", data.duration, sourceData.duration);
                data.enabledClear = Toggle("是否可清除:", data.enabledClear == 1,data.enabledClear == 1) ? 1 : 0;
                EditorGUILayout.HelpBox("叠加时重置护盾值和时长", MessageType.None);
                data.stack = IntField("叠加层数", data.stack, sourceData.stack);
            }

            if (data.type == 1 || data.type == 2 || data.type == 4 || data.type == 5)
            {
                GUILayout.Label("-----------------------------------------------------------");

                GUILayout.Label("属性修改");
                if (data.attr != null)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Type", EditorStyles.centeredGreyMiniLabel, GUILayout.Width(120f));
                    EditorGUILayout.LabelField("Value", EditorStyles.centeredGreyMiniLabel, GUILayout.Width(120f));
                    EditorGUILayout.EndHorizontal();

                    vt2BuffAttr = EditorGUILayout.BeginScrollView(vt2BuffAttr, GUILayout.MaxHeight(120f));

                    for (int i = 0; i < data.attr.Length; i++)
                    {
                        EditorGUILayout.BeginHorizontal();
                        data.attr[i].type = EditorGUILayout.TextField(data.attr[i].type, GUILayout.Width(120f));
                        EditorGUILayout.Space();
                        data.attr[i].value = EditorGUILayout.TextField(data.attr[i].value, GUILayout.Width(120f));
                        EditorGUILayout.Space();

                        if (GUILayout.Button("-"))
                        {
                            List<BuffAttrChange> list = new List<BuffAttrChange>(data.attr);
                            list.RemoveAt(i);
                            data.attr = list.ToArray();
                            //hasUnsavedChanges = true;
                        }

                        EditorGUILayout.EndHorizontal();
                    }
                    EditorGUILayout.EndScrollView();

                    if (data.attr.Length == 0)
                    {
                        data.attr = null;
                    }
                }

                if (GUILayout.Button("+"))
                {
                    if (data.attr == null)
                    {
                        data.attr = new BuffAttrChange[1] { new BuffAttrChange() };
                    }
                    else
                    {
                        List<BuffAttrChange> list = new List<BuffAttrChange>(data.attr);
                        list.Add(new BuffAttrChange());
                        data.attr = list.ToArray();
                    }
                    //hasUnsavedChanges = true;
                }
            }

            //GUILayout.Label("-----------------------------------------------------------");

            EditorGUILayout.EndVertical();
        }

        private void SetData(string dataAsset, CastSkillEditorData castSkillEditorData)
        {
            if(sourceData != null && data != null)
            {
                string txt1 = JsonConvert.SerializeObject(sourceData);
                string txt2 = JsonConvert.SerializeObject(data);
                if(txt1 != txt2)
                {
                    if(EditorUtility.DisplayDialog("保存", "您有未保存的改动", "保存", "取消"))
                    {
                        SaveChanges();
                    }
                }
            }

            this.dataAsset = dataAsset;
            this.sourceData = castSkillEditorData;
            this.data = JsonConvert.DeserializeObject<CastSkillEditorData>(JsonConvert.SerializeObject(castSkillEditorData));
        }

        private void OnDestroy()
        {
            if (spaceEditor != null)
            {
                spaceEditor.Close();
            }
        }

        GUIStyle StylePopup;
        GUIStyle StyleTextField;
        GUIStyle StyleToggle;

        private void InitStyle()
        {
            StylePopup = new GUIStyle(EditorStyles.popup)
            {
                fontStyle = FontStyle.Bold
            };

            StyleTextField = new GUIStyle(EditorStyles.textField) {
                fontStyle = FontStyle.Bold
            };

            StyleToggle = new GUIStyle(EditorStyles.toggle) {
                fontStyle = FontStyle.Bold
            };
        }

        private string TextField(string label,string value,string source)
        {
            return EditorGUILayout.TextField(label, value, value == source ? EditorStyles.textField: StyleTextField);
        }

        private int IntField(string label, int value, int source)
        {
            return EditorGUILayout.IntField(label, value, value == source ? EditorStyles.textField : StyleTextField);
        }

        private bool Toggle(string label, bool value, bool source)
        {
            return EditorGUILayout.Toggle(label, value, value == source ? EditorStyles.toggle : StyleToggle);
        }

        private float FloatField(string label, float value, float source)
        {
            return EditorGUILayout.FloatField(label, value, value == source ? EditorStyles.textField : StyleTextField);
        }

        private int Popup(string label,int value,string[] valueLabes ,int source)
        {
            return EditorGUILayout.Popup(label, value, valueLabes, value == source ? EditorStyles.popup : StylePopup, GUILayout.MinWidth(300f));
        }
    }
}